package club.ruanx.movie.adapter.impl;

import club.ruanx.acl.entity.SysParam;
import club.ruanx.acl.service.SysParamService;
import club.ruanx.exception.BaseException;
import club.ruanx.movie.adapter.SpiderMovieAdapter;
import club.ruanx.movie.adapter.interceptor.DoubanFileInterceptor;
import club.ruanx.movie.common.constraint.MovieParamConstraint;
import club.ruanx.movie.entity.Movie;
import club.ruanx.movie.util.FileUploaderWithFeign;
import club.ruanx.spider.entity.DoubanMovie;
import club.ruanx.spider.entity.DoubanPhotos;
import club.ruanx.util.CollectionUtils;
import club.ruanx.util.StringUtils;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 阮胜
 * @date 2019/1/28 13:09
 */
@Slf4j
@Component
public class SpiderMovieAdapterImpl implements SpiderMovieAdapter {
    private static final DateFormat FORMAT = new SimpleDateFormat("yyyy");
    private static final String PHOTOS_API_URL = "https://api.douban.com/v2/movie/subject/%s/photos?apikey=0b2bdeda43b5688921839c8ecb20399b&start=0&count=12&client=&udid=";
    private final SysParamService sysParamService;
    private final FileUploaderWithFeign fileUploaderWithFeign;

    public SpiderMovieAdapterImpl(SysParamService sysParamService, FileUploaderWithFeign fileUploaderWithFeign) {
        this.sysParamService = sysParamService;
        this.fileUploaderWithFeign = fileUploaderWithFeign;
    }

    @Override
    public Movie adapter(DoubanMovie doubanMovie) throws BaseException {
        String directors = parseDirector(doubanMovie);
        String actors = parseActor(doubanMovie);
        String types = parseTypes(doubanMovie);
        String areas = parseAreas(doubanMovie);
        String aka = parseAka(doubanMovie);
        String photos = parsePhotoField(doubanMovie);
        String cover = parseCover(doubanMovie);
        return Movie.builder()
                .id(doubanMovie.getId())
                .name(doubanMovie.getTitle())
                .rate((float) doubanMovie.getRating().getAverage())
                .cover(cover)
                .directors(directors)
                .actors(actors)
                .types(types)
                .initialReleaseDate(parseDate(doubanMovie.getYear()))
                .languages("[1,2,3]")
                .areas(areas)
                .duration("2小时")
                .introduction(doubanMovie.getSummary())
                .aka(aka)
                .photos(photos)
                .spiderId(doubanMovie.getId())
                .build();
    }

    private String parseCover(DoubanMovie doubanMovie) {
        String imgUrl = doubanMovie.getImages().getSmall();
        if (StringUtils.isEmpty(imgUrl)) {
            return "";
        }
        String largeImgUrl = imgUrl.replace("s_ratio_poster", "l");
        String urlJson = fileUploaderWithFeign.uploadImageFromUrl(Collections.singletonList(largeImgUrl));
        List<String> urls = JSON.parseArray(urlJson, String.class);
        if (CollectionUtils.isEmpty(urls)) {
            return "";
        }
        return urls.get(0);
    }

    private String parsePhotoField(DoubanMovie doubanMovie) {
        //初始化一个默认的文件拦截器
        DoubanFileInterceptor doubanFileInterceptor = file -> {
            try {
                BufferedImage bufferedImage = ImageIO.read(file);
                return bufferedImage.getWidth() > bufferedImage.getHeight();
            } catch (IOException e) {
                log.error(e.getMessage());
                return false;
            }
        };
        String url = String.format(PHOTOS_API_URL, doubanMovie.getId());
        try {
            String photoJson = Jsoup.connect(url).ignoreContentType(true).get().text();
            DoubanPhotos doubanPhotos = JSON.parseObject(photoJson, DoubanPhotos.class);
            List<DoubanPhotos.PhotosBean> photoList = doubanPhotos.getPhotos();
            if (CollectionUtils.isEmpty(photoList)) {
                return "";
            }
            List<String> imageUrlList = photoList.stream()
                    .map(DoubanPhotos.PhotosBean::getImage)
                    .filter(imageUrl -> !StringUtils.isEmpty(imageUrl))
                    .collect(Collectors.toList());
            return fileUploaderWithFeign.uploadImageFromUrl(imageUrlList, doubanFileInterceptor);
        } catch (Exception e) {
            log.error(e.getMessage());
            return "";
        }
    }

    private String parseAka(DoubanMovie doubanMovie) {
        List<String> akaList = doubanMovie.getAka();
        if (CollectionUtils.isEmpty(akaList)) {
            return "";
        }
        return akaList.get(0);
    }

    private String parseAreas(DoubanMovie doubanMovie) {
        List<SysParam> areaParamList = sysParamService.findAllByFlag(MovieParamConstraint.MOVIE_AREA);
        List<Integer> areaList = doubanMovie.getCountries().stream()
                .map(areaName -> areaParamList.stream()
                        .filter(sysParam -> sysParam.getName().contains(areaName))
                        .findFirst()
                        .map(sysParam -> Integer.valueOf(sysParam.getValue()))
                        .orElse(1))
                .distinct()
                .collect(Collectors.toList());
        return JSON.toJSONString(areaList);
    }


    private String parseTypes(DoubanMovie doubanMovie) {
        List<SysParam> typeParamList = sysParamService.findAllByFlag(MovieParamConstraint.MOVIE_TYPE);
        List<Integer> typeList = doubanMovie.getGenres().stream()
                .map(typeName -> typeParamList.stream()
                        .filter(sysParam -> sysParam.getName().contains(typeName))
                        .findFirst()
                        .map(sysParam -> Integer.valueOf(sysParam.getValue()))
                        .orElse(1))
                .distinct()
                .collect(Collectors.toList());
        return JSON.toJSONString(typeList);
    }

    private Date parseDate(String dateString) {
        try {
            return FORMAT.parse(dateString);
        } catch (ParseException e) {
            return new Date();
        }
    }

    private String parseDirector(DoubanMovie doubanMovie) {
        List<String> directorList = doubanMovie.getDirectors().stream()
                .map(DoubanMovie.DirectorsBean::getName)
                .collect(Collectors.toList());
        return StringUtils.collectionToCommaDelimitedString(directorList);
    }

    private String parseActor(DoubanMovie doubanMovie) {
        List<String> actorList = doubanMovie.getCasts().stream()
                .map(DoubanMovie.CastsBean::getName)
                .collect(Collectors.toList());
        return StringUtils.collectionToCommaDelimitedString(actorList);
    }

}
